﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bzure.Common.Transactions;

namespace Bzure.Common.Data
{
    public delegate void PostEntityHandler(IEntityRequestProcess EntityRequestProcessor, Bzure.Common.Data.EntityPostRequest EntityMap);
    public delegate T[] QueryEntityHandler<T>(IEntityRequestProcess EntityRequestProcessor,
Bzure.Common.Data.EntityQueryRequest<T> queryRequest) where T : Bzure.Common.Core.IEntity;
    public delegate Repository BuildRepositoryHandler();

    public interface IEntityRequestProcess : ITransactionSupport
    {
        /// <summary>
        /// 实体操作
        /// </summary>
        /// <param name="EntityMap"></param>
        void UpdateEntity(Bzure.Common.Data.EntityPostRequest EntityMap);
        /// <summary>
        /// 实体查询
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="queryRequest"></param>
        /// <returns></returns>
        T[] QueryEntity<T>(Bzure.Common.Data.EntityQueryRequest<T> queryRequest) where T : Bzure.Common.Core.IEntity, Bzure.Common.Core.IPersistenceState;
    }

    public abstract class EntityRequestProcessBase : IEntityRequestProcess, IEntityPostProcess
    {

        Dictionary<Type, PostEntityHandler> _postHandlers = new Dictionary<Type, PostEntityHandler>();
        Dictionary<Type, Delegate> _queryHandlers = new Dictionary<Type, Delegate>();

        Dictionary<Type, EntityUDHandler> _updateHandlers = new Dictionary<Type, EntityUDHandler>();
        Dictionary<Type, EntityUDHandler> _deleteHandlers = new Dictionary<Type, EntityUDHandler>();

        /// <summary>
        /// 事务上下文
        /// </summary>
        public Bzure.Common.Transactions.ITransactionContext TransactionContext { get; set; }
        public string TransactionName { get; set; }
        public EntityRequestProcessBase()
        {
        }
        /// <summary>
        /// 创建而不打开连接
        /// </summary>
        /// <returns></returns>
        public abstract System.Data.Common.DbConnection CreateConnection();
        /// <summary>
        /// 实体操作
        /// </summary>
        /// <param name="EntityMap"></param>
        public virtual void UpdateEntity(Bzure.Common.Data.EntityPostRequest EntityMap)
        {
            lock (_postHandlers)
            {
                InitEntityMap(EntityMap.Entity.GetType());

                PostEntityHandler handler;
                if (_postHandlers.TryGetValue(EntityMap.Entity.GetType(), out handler))
                {
                    handler(this, EntityMap);
                }

            }
        }
        /// <summary>
        /// 实体查询
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="queryRequest"></param>
        /// <returns></returns>
        public virtual T[] QueryEntity<T>(Bzure.Common.Data.EntityQueryRequest<T> queryRequest) where T : Bzure.Common.Core.IEntity, Bzure.Common.Core.IPersistenceState
        {
            lock (_queryHandlers)
            {
                InitEntityMap(typeof(T));

                Delegate handler;
                if (_queryHandlers.TryGetValue(typeof(T), out handler))
                {
                    QueryEntityHandler<T> h = handler as QueryEntityHandler<T>;
                    return h(this, queryRequest);
                }
            }
            return default(T[]);
        }
        public EntityPostRequest ToUpdateRequest(object entity)
        {
            lock (_updateHandlers)
            {
                Type type = entity.GetType();
                InitEntityMap(type);

                EntityUDHandler handler;
                if (_updateHandlers.TryGetValue(type, out handler))
                {
                    return handler(entity);
                }
                return default(EntityPostRequest);
            }
        }
        public EntityPostRequest ToDeleteRequest(object entity)
        {
            lock (_deleteHandlers)
            {
                Type type = entity.GetType();
                InitEntityMap(type);

                EntityUDHandler handler;
                if (_deleteHandlers.TryGetValue(type, out handler))
                {
                    return handler(entity);
                }
                return default(EntityPostRequest);
            }
        }
        void AppendEntityPostHandler(Type type, PostEntityHandler handler)
        {
            _postHandlers[type] = handler;
        }
        void AppendEntityQueryHandler<T>(QueryEntityHandler<T> handler) where T : Bzure.Common.Core.IEntity
        {
            _queryHandlers[typeof(T)] = handler;
        }
        void AppendEntityUpdateHandler(Type type, EntityUDHandler handler)
        {
            _updateHandlers[type] = handler;
        }
        void AppendEntityDeleteHandler(Type type, EntityUDHandler handler)
        {
            _deleteHandlers[type] = handler;
        }

        public void AppendEntityHandler<T>(Type TargetType, BuildRepositoryHandler handler) where T : Bzure.Common.Core.IEntity, Bzure.Common.Core.IPersistenceState
        {
            if (TargetType == typeof(T))
            {
                AppendEntityPostHandler(typeof(T), (p, m) => handler().ProcessEntityPostRequest<T>(m));
                AppendEntityQueryHandler<T>((p, m) => handler().ProcessEntityQueryRequest<T>(m));
                AppendEntityUpdateHandler(typeof(T), (m) => handler().ConvertToTemplateRepository ().ToUpdateRequest(m));
                AppendEntityDeleteHandler(typeof(T), (m) => handler().ConvertToTemplateRepository().ToDeleteRequest(m));


            }
        }
        public abstract void InitEntityMap(Type type);
    }
    public static class RepositoryExtensions
    {
        public static TemplateRepository ConvertToTemplateRepository(this Repository Repository)
        {
            TemplateRepository TR = Repository as TemplateRepository;
            return TR;
        }
    }
}
